from collections import OrderedDict
from datetime import datetime
from time import time
import json

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet

from .serializer import *
from util.auth import OWNTokenAuthentication
from util.page import MyPageNumberPagination
from util.exception import ValidationError
from util.anaFile import AnaFile
from util.jsonDeal import JsonDeal
from util.simTool import SIMTool
from util.change_to_d import change_to_d, r_c
from apps.missions.models import Mission
from .tasks import active_task


class GatewayView(GenericViewSet):
    authentication_classes = [OWNTokenAuthentication]

    @action(detail=False, methods=["POST", ], url_path="create")
    def gateway_create(self, requests, *args, **kwargs):
        serializer = GatewaySerializer(data=self.request.data)
        if serializer.is_valid():
            key = serializer.create(serializer.validated_data)
            return Response({"code": 200, "msg": "添加用户成功", "key": key})
        raise ValidationError(20001)

    @action(detail=False, methods=["GET", ], url_path="list")
    def gateway_list(self, requests, *args, **kwargs):
        data = {"gateway_id": requests.GET.get("gateway_id"), "state": requests.GET.get("state"),
                "model_number": requests.GET.get("model_number"), "active_state": requests.GET.get("active_state"),
                "script_id": requests.GET.get("script_id"), "order": requests.GET.get("order", -1),
                "is_tac31": requests.GET.get("is_tac31", False), "sim_number": requests.GET.get("sim_number")}
        serializers = GatewayListCheckSerializer(data=data)
        if serializers.is_valid():
            gateways = Gateway.objects
            gateway_id = serializers.validated_data.get("gateway_id")
            state = serializers.validated_data.get("state")
            model_number = serializers.validated_data.get("model_number")
            active_state = serializers.validated_data.get("active_state")
            script_id = serializers.validated_data.get("script_id")
            order = serializers.validated_data.get("order", -1)
            sim_number = serializers.validated_data.get("sim_number")
            if gateway_id:
                gateways = gateways.filter(gateway_id__icontains=gateway_id)
            if state is not None:
                gateways = gateways.filter(state=state)
            if model_number:
                gateways = gateways.filter(model_number__icontains=model_number)
            if active_state is not None:
                gateways = gateways.filter(active_state=active_state)
            if script_id:
                gateways = gateways.filter(script_id=script_id)
            if order == 1:
                gateways = gateways.order_by("create_date")
            if sim_number:
                gateways = gateways.filter(sim_number__icontains=sim_number)
            gateways = gateways.order_by("create_date")
            if order is None or order == -1:
                gateways = gateways.order_by("-create_date")
            gateways = gateways.filter(is_delete=False).all()
            page = MyPageNumberPagination()
            page_usrs = page.paginate_queryset(queryset=gateways, request=requests, view=self)
            gateway_re = GatewayListSerializer(instance=page_usrs, many=True)
            return Response(self.__get_paginated_response(page, requests, gateway_re.data))
        else:
            raise ValidationError(20001)

    def __get_paginated_response(self, page, request, datas):
        datas = self.__struct_data(datas)
        a = OrderedDict([
            ('current', int(page.get_page_number(request, page))),
            ('total', int(page.page.paginator.count)),
            ('pageSize', int(page.get_page_size(request))),
            ('data', datas)
        ])
        return a

    def __struct_data(self, datas):
        for data in datas:
            data["debugList"] = []
            data["instructList"] = []
            data["checkedList"] = []
            description = []
            data["description"] = description
            sensors = Sensor.objects.filter(is_delete=False, gateway_id=data["key"]).order_by("number").all()
            for sensor in sensors:
                id = sensor.id
                number = sensor.number
                description.append({
                    "label": "".join(["传感器", str(number)]),
                    "index": number,
                    "value": id,
                    "disabled": False
                })
        return datas

    @action(detail=False, methods=["POST", ], url_path="active")
    def gateway_active(self, requests, *args, **kwargs):
        data = {}
        data["name"] = requests.data.get("name")
        data["script_id"] = requests.data.get("script_id")
        data["key"] = requests.data.get("key")
        data["active_state"] = 0
        serializer = GatewayActiveSerializer(data=data)
        if serializer.is_valid():
            gateway = serializer.create(serializer.validated_data)
            if gateway:
                if not gateway.is_tac31:
                    file_path = "".join([settings.DEPLOY_JSON_FILE_DIR, "/", str(gateway.gateway_id), ".json"])
                    mission_id = str(uuid4()).replace("-", "")
                    Mission.objects.create(id=mission_id, key=gateway.key, gateway_id=gateway.gateway_id,
                                           mission_number=settings.UPLOAD_DEPLOY, file_path=file_path)
                    data = {
                        "gateway_id": gateway.key,
                        "mission_id": mission_id
                    }
                    active_task.delay(data)
                return Response({"code": 200, "msg": "添加用户成功", "key": gateway.key})
            else:
                raise ValidationError(30002)
        else:
            raise ValidationError(20001)

    @action(detail=False, methods=["POST", ], url_path="active_again")
    def gateway_active_again(self, requests, *args, **kwargs):
        key = requests.data.get("key")
        gateway = Gateway.objects.filter(key=key).first()
        mission_id = str(uuid4()).replace("-", "")
        file_path = "".join([settings.DEPLOY_JSON_FILE_DIR, "/", str(gateway.gateway_id), ".json"])
        Mission.objects.create(id=mission_id, key=key, gateway_id=gateway.gateway_id,
                               mission_number=settings.UPLOAD_DEPLOY, file_path=file_path)
        if gateway:
            data = {"mission_id": mission_id}
            active_task.delay(data)
            return Response({"code": 200, "msg": "激活中"})
        else:
            raise ValidationError(30002)

    @action(detail=False, methods=["POST", ], url_path="update")
    def gateway_update(self, requests, *args, **kwargs):
        data = {}
        data["key"] = requests.data.get("key")
        data["script_id"] = requests.data.get("script_id")
        data["update_date"] = datetime.now()
        data["is_delete"] = requests.data.get("is_delete", False)
        serializer = GatewayUpdateSerializer(data=data)
        if serializer.is_valid():
            gateway = Gateway.objects.filter(key=data["key"]).first()
            serializer.update(gateway, serializer.validated_data)
            return Response({"code": 200, "msg": "修改成功"})
        else:
            raise ValidationError(20001)

    @action(detail=False, methods=["GET", ], url_path="down_deploy")
    def down_deploy(self, requests, *args, **kwargs):
        key = requests.GET.get("key", "")
        gateway = Gateway.objects.filter(key=key).first()
        file_path = "".join([settings.DEPLOY_FILE_DIR, "/", str(gateway.gateway_id), ".json"])
        if os.path.isfile(file_path):
            try:
                with open(file_path, "r", encoding="utf-8") as f:
                    content = json.load(f)
            except Exception as e:
                raise ValidationError(60005)
            return Response({"code": 200, "msg": "获取文件成功", "result": content})
        else:
            raise ValidationError(50004)

    @action(detail=False, methods=["POST", ], url_path="upload_deploy")
    def upload_deploy(self, requests, *args, **kwargs):
        key = requests.data.get("key", "")
        content = requests.data.get("content")
        data = content.get("data")
        ana_file = AnaFile(data)
        gateway = Gateway.objects.filter(key=key).first()
        if content:
            file_path = "".join([settings.DEPLOY_FILE_DIR, "/", str(gateway.gateway_id), ".json"])
            self.__upload_deploy(file_path, content)
            sensor_ids = ana_file.ana_file()
            self.__add_sensor(gateway.key, sensor_ids)
            tia_file_path = "".join([settings.DEPLOY_JSON_FILE_DIR, "/", str(gateway.gateway_id), ".json"])
            try:
                JsonDeal.get_tia(data, tia_file_path)
            except:
                with open(tia_file_path, "w", encoding="utf-8") as f:
                    content = change_to_d(content, r_c)
                    json.dump(content, f)
            return Response({"code": 200, "msg": "上传成功"})
        else:
            raise ValidationError(20001)

    def __upload_deploy(self, filepath, content):
        try:
            with open(filepath, 'w') as f:
                json.dump(content, f)
        except Exception as e:
            raise ValidationError(60003)

    def __add_sensor(self, key, sensor_ids):
        Sensor.delete_sensors(key)
        sensors = []
        for sensor_id in sensor_ids:
            sensors.append(Sensor(id=str(uuid4()).replace("-", ""), number=sensor_id, gateway_id=key))
        Sensor.objects.bulk_create(sensors)

    @action(detail=False, methods=["GET", ], url_path="gateway_list")
    def gateway_list_alone(self, requests, *args, **kwargs):
        gateways = Gateway.objects.filter(is_delete=False).all()
        datas = []
        for gateway in gateways:
            children = []
            sensors = Sensor.objects.filter(gateway_id=gateway.key).all()
            for sensor in sensors:
                children.append({
                    "value": sensor.id,
                    "label": sensor.number
                })
            datas.append({
                "value": gateway.key,
                "label": gateway.name,
                "children": children
            })
        return Response({
            "code": 200,
            "result": datas
        })

    @action(detail=False, methods=["POST", ], url_path="sim_number")
    def sim_number(self, requests, *args, **kwargs):
        key = requests.data.get("key", "")
        sim_number = requests.data.get("sim_number")
        data = {}
        data["key"] = key
        data["sim_number"] = sim_number
        serializer = GatewaySIMNumberSerializer(data=data)
        if serializer.is_valid():
            gateway = Gateway.objects.filter(key=serializer.validated_data.get("key")).first()
            serializer.update(gateway, serializer.validated_data)
            return Response({"code": 200, "msg": "添加成功"})
        else:
            raise ValidationError(20001)
